<?php

declare(strict_types=1);

namespace App\Service\Access;

use App\Model\CustomModuleData;

/**
 * 自定义模块数据-数据访问类
 */
class CustomModuleDataAccess extends BaseAccess
{
        /**
         * 允许连接的表信息
         * @var array
         */
        public array $allowJoinsTableInfo = [];

        /**
         * 初始化
         * @param array $inject
         * @return $this
         */
        public function init(array $inject = []): CustomModuleDataAccess
        {
                $this->wheres = [];
                $arrWhereKeys = [
                        'customModuleDataId', 'customModuleDataIds', 'customModuleId', 'customModuleIds',
                        'status', 'createTimeBetween', 'updateTimeBetween',
                ];
                $arrParams = $inject['wheres'] ?? $this->getRequestPrams('inputs', $arrWhereKeys);
                if (isset($inject['mergeWheres'])) $arrParams = array_merge($arrParams, $inject['mergeWheres']);
                foreach ($arrWhereKeys as $v) {
                        $mixedValue = $arrParams[$v] ?? null;
                        if ($mixedValue === null) continue;
                        switch ($v) {
                                case 'customModuleDataIds':
                                case 'customModuleIds':
                                        $strField = substr($v, 0, -1);
                                        $this->wheres[] = ['whereIn', 'custom_module_data.' . $strField, $mixedValue];
                                        break;
                                case 'createTimeBetween':
                                case 'updateTimeBetween':
                                        $strField = 'custom_module_data.' . substr($v, 0, -7);
                                        isset($mixedValue['start']) && $this->wheres[] = [$strField, '>=', $mixedValue['start']];
                                        isset($mixedValue['end']) && $this->wheres[] = [$strField, '<=', $mixedValue['end']];
                                        break;
                                default:
                                        $this->wheres[] = ['custom_module_data.' . $v, '=', $mixedValue];
                        }
                }
                $this->fields = [
                        'custom_module_data.customModuleDataId', 'custom_module_data.customModuleId',
                        'custom_module_data.status',  'custom_module_data.sort',
                        'custom_module_data.createTime', 'custom_module_data.updateTime'
                ];
                $this->orders = ['custom_module_data.sort' => 'desc', 'custom_module_data.customModuleDataId' => 'desc'];
                $this->groups = [];
                $this->page = intval($inject['page'] ?? $this->getRequestPrams('input', 'page', 1));
                $this->limit = intval($inject['limit'] ?? $this->getRequestPrams('input', 'limit', 10));
                if (isset($inject['joins'])) {
                        foreach ($inject['joins'] as $k => $v) {
                                $strTable = explode(' ', $v['table'])[0];
                                if (!isset($this->allowJoinsTableInfo[$strTable])) {
                                        unset($inject['joins'][$k]);
                                        continue;
                                }
                                $this->fields = array_merge($this->fields, $this->allowJoinsTableInfo[$strTable]['fields']);
                        }
                        $this->joins = $inject['joins'];
                }
                if ($arrSpecifyOrderBy = ($inject['orders'] ?? $this->getRequestPrams('input', 'orders'))) {
                        $this->orders = [];
                        $arrOrderBy = arrayKeyBlurSearch($arrSpecifyOrderBy, $this->fields);
                        foreach ($arrOrderBy as $k => $v) {
                                if (($strReplace = strstr($k, ' AS ')) !== false) {
                                        $k = str_replace($strReplace, '', $k);
                                }
                                $this->orders[$k] = $v;
                        }
                }
                if ($arrSpecifyGroupBy = ($inject['groups'] ?? $this->getRequestPrams('input', 'groups'))) {
                        $arrGroupBy = array_intersect(arrayBlurSearch($this->fields, $arrSpecifyGroupBy), $this->fields);
                        foreach ($arrGroupBy as $v) {
                                if (($strReplace = strstr($v, ' AS ')) !== false) {
                                        $v = str_replace($strReplace, '', $v);
                                }
                                $this->groups[] = $v;
                        }
                }
                if ($arrSpecifyFields = ($inject['fields'] ?? $this->getRequestPrams('input', 'fields'))) {
                        $this->fields = array_intersect(arrayBlurSearch($this->fields, $arrSpecifyFields), $this->fields);
                }
                return $this;
        }

        /**
         * 获取模型
         * @return CustomModuleData
         */
        public function getModel(): CustomModuleData
        {
                return new CustomModuleData();
        }

        /**
         * 生成模型
         * @return object
         */
        public function makeModel(): object
        {
                $objModel = $this->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                $objModel = $this->inputFields($objModel, $this->fields);
                $objModel = $this->inputOrders($objModel, $this->orders);
                return $this->inputGroups($objModel, $this->groups);
        }

        /**
         * 查询分页
         * @param array $inject
         * @return array
         */
        public function paginate(array $inject = []): array
        {
                return $this->init($inject)->queryPaginate($this->makeModel(), $this->page, $this->limit);
        }

        /**
         * 查询指定页
         * @param array $inject
         * @return array
         */
        public function forPage(array $inject = []): array
        {
                return $this->init($inject)->queryForPage($this->makeModel(), $this->page, $this->limit);
        }

        /**
         * 查询一行
         * @param array $inject
         * @return array
         */
        public function first(array $inject = []): array
        {
                return $this->init($inject)->queryFirst($this->makeModel());
        }

        /**
         * 查询列
         * @param array $inject
         * @return array
         */
        public function pluck(array $inject = []): array
        {
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                $objModel = $this->inputOrders($objModel, $this->orders);
                return $this->queryPluck($objModel, $inject['column'], $inject['key'] ?? null);
        }

        /**
         * 查询值
         * @param array $inject
         * @return mixed
         */
        public function value(array $inject = []): mixed
        {
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                $objModel = $this->inputOrders($objModel, $this->orders);
                return $this->queryValue($objModel, $inject['column']);
        }

        /**
         * 汇总
         * @param array $inject
         * @return int
         */
        public function count(array $inject = []): int
        {
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                return $this->queryCount($objModel, $inject['column'] ?? '*');
        }

        /**
         * 查询是否存在
         * @param array $inject
         * @return bool
         */
        public function exists(array $inject = []): bool
        {
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                return $objModel->exists();
        }

        /**
         * 主键查找单个
         * @param mixed $id
         * @param array $fields
         * @return array
         */
        public function find(mixed $id, array $fields = ['*']): array
        {
                return $this->queryFind($this->getModel(), $id, $fields);
        }

        /**
         * 主键查找多个
         * @param array $ids
         * @param array $fields
         * @return array
         */
        public function finds(array $ids, array $fields = ['*']): array
        {
                return $this->queryFind($this->getModel(), $ids, $fields);
        }

        /**
         * 插入
         * @param array $insert
         * @return bool
         */
        public function insert(array $insert): bool
        {
                if (!$insert) return false;
                return $this->getModel()->insert($insert);
        }

        /**
         * 插入并返回主键id
         * @param array $insert
         * @return int
         */
        public function insertGetId(array $insert): int
        {
                if (!$insert) return 0;
                return $this->getModel()->insertGetId($insert);
        }

        /**
         * 更新
         * @param array $inject
         * @return int
         */
        public function update(array $inject = []): int
        {
                if (!isset($inject['wheres']) || !isset($inject['update'])) return 0;
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                return intval($objModel->update($inject['update']));
        }

        /**
         * 根据主键id更新
         * @param array $update
         * @return int
         */
        public function updateById(array $update): int
        {
                return $this->accordingToPrimaryKeyUpdate($this->getModel(), $update);
        }

        /**
         * 删除
         * @param array $inject
         * @return int
         */
        public function delete(array $inject = []): int
        {
                if (!isset($inject['wheres'])) return 0;
                $objModel = $this->init($inject)->getModel();
                $objModel = $this->inputJoins($objModel, $this->joins);
                $objModel = $this->inputWheres($objModel, $this->wheres);
                return intval($objModel->delete());
        }

        /**
         * 批量插入
         * @param array $inserts
         * @param int $size
         * @return array
         */
        public function batchInsert(array $inserts, int $size = 500): array
        {
                return $this->chunkBatchInsert($this->getModel(), $inserts, $size);
        }

        /**
         * 批量更新
         * @param array $updates
         * @param int $size
         * @return array
         */
        public function batchUpdate(array $updates, int $size = 500): array
        {
                return $this->chunkBatchUpdate($this->getModel(), $updates, $size);
        }


}